﻿//Copyright (c) 2010-2011, Andreas Grünwald
//All rights reserved.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Threading;
using System.Threading;
using yaTDL.Core.UI;

namespace yaTDL.Core.MVVM
{
    public class ProjectListViewModel:ViewModelBase
    {
        #region Fields

        RelayCommand _addProjectCommand;
        RelayCommand _editProjectCommand;
        RelayCommand _deleteProjectCommand;        

        ObservableCollection<Project> _projects = new ObservableCollection<Project>();
        Project _selectedProject;

        ProjectTaskListViewModel _taskListViewModel;
        Visibility _taskListVisibility = Visibility.Hidden;


        #endregion

        #region Public Properties

        public ICommand AddProjectCommand 
        {
            get 
            {
                if( _addProjectCommand == null)
                { _addProjectCommand = new RelayCommand(p => this.addProjectCommandExecute(p)); } 
                return _addProjectCommand;
            }
        }

        public ICommand DeleteProjectCommand
        {
            get
            {
                if (_deleteProjectCommand == null)
                {
                    _deleteProjectCommand = new RelayCommand(p => this.deleteProjectCommandExecute(p), p => this.deleteProjectCommandCanExecute(p));
                }
                return _deleteProjectCommand;
            }
        }

        public ICommand EditProjectCommand
        {
            get
            {
                if (_editProjectCommand == null)
                {
                    _editProjectCommand = new RelayCommand(p => this.editProjectCommandExecute(p), p => this.editProjectCommandCanExecute(p));
                }
                return _editProjectCommand;
            }
        }


        public ObservableCollection<Project> Projects
        {
            get { return _projects; }
            set { _projects = value; }
        }

        public Project SelectedProject
        {
            get {return _selectedProject;}
            set
            {
                if (value != _selectedProject)
                {
                    _selectedProject = value;
                    RaisePropertyChanged("SelectedProject");

                    
                    if (_selectedProject == null)
                    {
                        TaskListViewModel = null;
                        TaskListVisibility = Visibility.Hidden;
                    }
                    else
                    {
                        if (TaskListViewModel == null)
                        {
                            TaskListViewModel = new ProjectTaskListViewModel(SelectedProject.Id);
                        }

                        TaskListViewModel.ProjectId = _selectedProject.Id;
                        TaskListVisibility = Visibility.Visible;
                        
                    }

                }
            }
        }

        public ProjectTaskListViewModel TaskListViewModel
        {
            get
            { return _taskListViewModel; }
            set
            {
                if (value != _taskListViewModel)
                {
                    _taskListViewModel = value;
                    RaisePropertyChanged("TaskListViewModel");
                }
            }
        }

        public Visibility TaskListVisibility
        {
            get { return _taskListVisibility; }
            set
            {
                if (value != _taskListVisibility)
                {
                    _taskListVisibility = value;
                    RaisePropertyChanged("TaskListVisibility");
                }
            }
        }

        #endregion

        #region Private Properties

        private bool isProjectSelected { get { return SelectedProject == null ? false : true; } }

        #endregion


        #region Constructor and Private Methods

        public ProjectListViewModel()
        {
            foreach (Project p in TaskStore.GetProjects())
            {
                Projects.Add(p);
            }

            Projects.Add(new Project() { Name = "No Project", Id = "0" });


            TaskStore.ProjectAdded += new EventHandler<ProjectEventArgs>(TaskStore_ProjectAdded);
            TaskStore.ProjectDeleted += new EventHandler<ProjectEventArgs>(TaskStore_ProjectDeleted);
        }        
        

        private void TaskStore_ProjectDeleted(object sender, ProjectEventArgs e)
        {
            List<Project> deletedProjects = (from project in Projects
                                            where project.Id == e.ProjectId
                                            select project).ToList<Project>();

            foreach (Project p in deletedProjects)
            {
                Projects.Remove(p);
            }            
        }

        private void TaskStore_ProjectAdded(object sender, ProjectEventArgs e)
        {
            if (Application.Current.Dispatcher.CheckAccess())
            {
                Projects.Insert(Projects.Count - 1, TaskStore.GetProject(e.ProjectId));
            }
            else
            {
                Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(delegate() { Projects.Insert(Projects.Count - 1, TaskStore.GetProject(e.ProjectId)); }));
            }              
        }


        private void editProjectCallback(object parameter)
        {
            if (!(parameter as InputBoxViewModel).WasCanceled)
            {
                string newName = (parameter as InputBoxViewModel).Text;
                string originalName = (parameter as InputBoxViewModel).OriginalText;

                if (TaskStore.ProjectNameExists(newName) && newName != originalName)
                {
                    yaTDL.Core.UI.Dialogs.ShowMessageBox("A Project with that name already exists.\nPlease choose another Name", "", MessageBoxButton.OK, MessageBoxImage.Error);
                    editProjectCommandExecute(null);
                }
                else
                {
                    SelectedProject.Name = newName;
                }
            }                
        }

        #endregion

        #region Command Methods

        public void addProjectCommandExecute(object parameter)
        {
            Project p = new Project() { Name = "New Project" };

            int i = 2;
            while (TaskStore.ProjectNameExists(p.Name))
            {
                p.Name = String.Format("New Project ({0})", i);
                i++;
            }

            TaskStore.AddProject(p);
            this.SelectedProject = p;

            if (editProjectCommandCanExecute(null))
                editProjectCommandExecute(null);
        }

        private bool editProjectCommandCanExecute(object paramter)
        {
            return deleteProjectCommandCanExecute(null);
        }

        private void editProjectCommandExecute(object parameter)
        {
            InputBoxViewModel vm = new InputBoxViewModel();

            vm.Title = "rename project";
            vm.Text = SelectedProject.Name;

            ViewManager.ShowView(vm, this.editProjectCallback);

        }



        private bool deleteProjectCommandCanExecute(object parameter) 
        {
            if (SelectedProject != null)
            {
                if (SelectedProject.Id == "0" || String.IsNullOrEmpty(SelectedProject.Id))
                { return false; }
                else
                {
                    return true;
                }
            }
            else
            {
                return isProjectSelected;
            }
        }

        private void deleteProjectCommandExecute(object parameter)
        {
            //TODO: request confirmation

            MessageBoxResult result = Dialogs.ShowMessageBox("Are you sure you want to delete the selected Project?\n All tasks in the Project will become \"project-less\" and show up under \"No Project\".", "Please Confirm",
                MessageBoxButton.YesNo, MessageBoxImage.Question);


            if (result == MessageBoxResult.Yes)
            {
                int projectIndex = Projects.IndexOf(SelectedProject);                

                TaskStore.RemoveProject(SelectedProject.Id);
                
                SelectedProject = projectIndex > Projects.Count - 1 ? Projects.Last() : Projects[projectIndex];
            }
            
        }

        #endregion

    }
}
